package indi.zhifa.recipe.bailan.framework.enums.service.impl;
import indi.zhifa.recipe.bailan.framework.common.entity.exception.ServiceException;
import indi.zhifa.recipe.bailan.framework.common.util.DtoEntityUtil;
import indi.zhifa.recipe.bailan.framework.enums.dao.service.ITypeDbService;
import indi.zhifa.recipe.bailan.framework.enums.dao.service.ITypeItemDbService;
import indi.zhifa.recipe.bailan.framework.enums.entity.dto.*;
import indi.zhifa.recipe.bailan.framework.enums.entity.po.SysTypeEntity;
import indi.zhifa.recipe.bailan.framework.enums.entity.po.SysTypeItemEntity;
import indi.zhifa.recipe.bailan.framework.enums.entity.vo.SysTypeItemVo;
import indi.zhifa.recipe.bailan.framework.enums.entity.vo.SysTypeVo;
import indi.zhifa.recipe.bailan.framework.enums.service.ISysTypeMemo;
import indi.zhifa.recipe.bailan.framework.enums.service.ITypeMgrService;
import indi.zhifa.recipe.bailan.framework.mysql.entity.annotations.ZfFacade;
import indi.zhifa.recipe.bailan.framework.mysql.utils.DbDtoEntityUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@ZfFacade(name = "类型管理")
public class TypeMgrServiceImpl implements ITypeMgrService {

    private final ITypeDbService mTypeDbService;
    private final ITypeItemDbService mTypeItemDbService;
    private final ISysTypeMemo mISysTypeMemo;

    public void init(){
        List<SysTypeEntity> sysTypeEntityList = mTypeDbService.list();
        List<SysTypeVo> sysTypeVoList = DtoEntityUtil.trans(sysTypeEntityList,SysTypeVo.class);
        for(SysTypeVo sysTypeVo : sysTypeVoList){
            List<SysTypeItemEntity> itemEntityList = mTypeItemDbService.listByTypeId(sysTypeVo.getId());
            List<SysTypeItemVo> sysTypeItemVoList =  DtoEntityUtil.trans(itemEntityList,SysTypeItemVo.class);
            sysTypeVo.setItems(sysTypeItemVoList);
            mISysTypeMemo.memo(sysTypeVo);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysTypeVo create(SysTypeCreateDto pSysTypeCfg) {
        if(mTypeDbService.existByCode(pSysTypeCfg.getCode())){
            throw new ServiceException("已经存在名为"+pSysTypeCfg.getCode()+"的类型");
        }
        SysTypeEntity typeEntity = DbDtoEntityUtil.createFromDto(pSysTypeCfg, SysTypeEntity.class);
        mTypeDbService.save(typeEntity);
        SysTypeVo sysTypeVo = DtoEntityUtil.trans(typeEntity,SysTypeVo.class);
        mISysTypeMemo.memo(sysTypeVo);
        return sysTypeVo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysTypeVo edit(Long pId, SysTypeEditDto pSysTypeEditCfg) {
        SysTypeEntity orgSysTypeEntity = mTypeDbService.check(pId);
        SysTypeEntity newSysTypeEntity = DbDtoEntityUtil.editByDto(orgSysTypeEntity,pSysTypeEditCfg,SysTypeEntity.class);
        mTypeDbService.updateById(newSysTypeEntity);
        List<SysTypeItemEntity> sysTypeItemEntityList = mTypeItemDbService.listByTypeId(pId);
        SysTypeVo sysTypeVo = DtoEntityUtil.trans(newSysTypeEntity,SysTypeVo.class);
        List<SysTypeItemVo> sysTypeItemVoList =  DtoEntityUtil.trans(sysTypeItemEntityList,SysTypeItemVo.class);
        sysTypeVo.setItems(sysTypeItemVoList);
        mISysTypeMemo.memo(sysTypeVo);
        return sysTypeVo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysTypeVo edit(Long pId, SysTypeEditAllDto pSysTypeEditAllDto) {
        SysTypeEntity orgSysTypeEntity = mTypeDbService.check(pId);
        SysTypeEntity newSysTypeEntity = DbDtoEntityUtil.editByDto(orgSysTypeEntity,pSysTypeEditAllDto,SysTypeEntity.class);
        mTypeDbService.updateById(newSysTypeEntity);
        mTypeItemDbService.removeByTypeId(pId);
        List<SysTypeItemEntity> typeItemEntityList = DbDtoEntityUtil.trans(pSysTypeEditAllDto.getItems(),SysTypeItemEntity.class);
        for(int i=0;i<typeItemEntityList.size();i++){
            SysTypeItemEntity sysTypeItemEntity = typeItemEntityList.get(i);
            sysTypeItemEntity.createInit();
            sysTypeItemEntity.setSortOrder(i+1);
            sysTypeItemEntity.setTypeId(pId);
            sysTypeItemEntity.setTypeCode(newSysTypeEntity.getCode());
        }
        mTypeItemDbService.saveBatch(typeItemEntityList);
        SysTypeVo sysTypeVo = DtoEntityUtil.trans(newSysTypeEntity,SysTypeVo.class);
        List<SysTypeItemVo> sysTypeItemVoList = DtoEntityUtil.trans(typeItemEntityList,SysTypeItemVo.class);
        sysTypeVo.setItems(sysTypeItemVoList);
        mISysTypeMemo.memo(sysTypeVo);
        return sysTypeVo;
    }

    protected SysTypeVo infoFromDb(Long pId){
        SysTypeEntity sysTypeEntity = mTypeDbService.check(pId);
        List<SysTypeItemEntity> sysTypeItemEntityList = mTypeItemDbService.listByTypeId(pId);
        SysTypeVo sysTypeVo = DtoEntityUtil.trans(sysTypeEntity,SysTypeVo.class);
        List<SysTypeItemVo> sysTypeItemVoList = DtoEntityUtil.trans(sysTypeItemEntityList,SysTypeItemVo.class);
        sysTypeVo.setItems(sysTypeItemVoList);
        return sysTypeVo;
    }

    @Override
    public SysTypeVo info(Long pId) {
        SysTypeVo sysTypeVo = mISysTypeMemo.infoFromMemo(pId);
        if(null == sysTypeVo){
            throw new ServiceException("缓存中没有找到id为"+pId+"的类型");
        }
        return sysTypeVo;
    }

    @Override
    public SysTypeVo info(String pCode) {
        SysTypeVo sysTypeVo = mISysTypeMemo.infoFromMemo(pCode);
        if(null == sysTypeVo){
            throw new ServiceException("缓存中没有找到code为"+pCode+"的类型");
        }
        return sysTypeVo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysTypeItemEntity addItem(Long pTypeId, SysTypeItemCreateDto pSysTypeItemCreateCfg) {
        SysTypeEntity sysTypeEntity = mTypeDbService.check(pTypeId);
        SysTypeItemEntity sysTypeItemEntity = DbDtoEntityUtil.createFromDto(pSysTypeItemCreateCfg,SysTypeItemEntity.class);
        sysTypeItemEntity.setTypeId(sysTypeEntity.getId());
        sysTypeItemEntity.setTypeCode(sysTypeEntity.getCode());
        List<SysTypeItemEntity> sysTypeItemEntityList = mTypeItemDbService.listByTypeId(pTypeId);
        Set<Integer> codeSet = sysTypeItemEntityList.stream().map(SysTypeItemEntity::getCode).collect(Collectors.toSet());
        if(codeSet.contains(pSysTypeItemCreateCfg.getCode())){
            throw new ServiceException("类型"+sysTypeEntity.getCode()+"已存在编号为"+pSysTypeItemCreateCfg.getCode()+"的code的类型项");
        }
        Set<String> nameSet = sysTypeItemEntityList.stream().map(SysTypeItemEntity::getName).collect(Collectors.toSet());
        if(nameSet.contains(pSysTypeItemCreateCfg.getName())){
            throw new ServiceException("类型"+sysTypeEntity.getCode()+"已存在名为"+pSysTypeItemCreateCfg.getCode()+"的name的类型项");
        }

        sysTypeItemEntity.setSortOrder(sysTypeItemEntityList.size()+1);
        mTypeItemDbService.save(sysTypeItemEntity);
        SysTypeVo sysTypeVo = infoFromDb(pTypeId);
        mISysTypeMemo.memo(sysTypeVo);
        return sysTypeItemEntity;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysTypeItemEntity editItem(Long pTypeItemId, SysTypeItemEditDto pSysTypeItemEditCfg) {
        SysTypeItemEntity orgSysTypeItemEntity = mTypeItemDbService.check(pTypeItemId);
        SysTypeItemEntity newSysTypeItemEntity = DbDtoEntityUtil.editByDto(orgSysTypeItemEntity,pSysTypeItemEditCfg,SysTypeItemEntity.class);
        mTypeItemDbService.updateById(newSysTypeItemEntity);
        SysTypeVo sysTypeVo = infoFromDb(orgSysTypeItemEntity.getTypeId());
        mISysTypeMemo.memo(sysTypeVo);
        return newSysTypeItemEntity;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteTypeItem(Long pTypeItemId) {
        SysTypeItemEntity typeItemEntity = mTypeItemDbService.check(pTypeItemId);
        mTypeItemDbService.removeById(pTypeItemId);
        SysTypeVo sysTypeVo = infoFromDb(typeItemEntity.getTypeId());
        mISysTypeMemo.memo(sysTypeVo);
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteType(Long pTypeId) {
        SysTypeEntity sysTypeEntity = mTypeDbService.check(pTypeId);
        mTypeDbService.removeById(pTypeId);
        mISysTypeMemo.delete(sysTypeEntity);
        return true;
    }
}
